<?php
namespace statistics\utils;
use statistics\utils\DBAccess;
use statistics\model\statistic\Statistic;
use statistics\model\statistic\StatisticTable;
use statistics\model\statistic\StatisticTableRow;
use statistics\model\statistic\StatisticTableColumn;
use statistics\model\statistic\StatisticCondition;
use statistics\model\statistic\StatisticFunction;

require_once(substr(__DIR__, 0, strpos(__DIR__, 'statistics')+10). DIRECTORY_SEPARATOR .'includes.php');

class StatisticPersistenceService{
	
	const DEFAULT_STATISTIC_ID = 1;
	private $staDBHandler;
	
	private static $instance = null;
	
	public static function getInstance()
	{
		if (self::$instance === null)
		{
			self::$instance = new self;
		}
		return self::$instance;
	}
	
	private function __construct() {
		$this->staDBHandler = DBAccess::getInstance();
	}
	
	private function fetchStatisticConfigurations() {
		global $gCurrentOrganization;
	
		$allStatisticConfigurations = array();
		
		// IDs und Namen vorhandener Statistik-Konfigurationen aus der DB holen
		$allStatisticConfigIDs = $this->getStatisticIDs ( $gCurrentOrganization->getValue ( 'org_id', '' ) );
		foreach ( $allStatisticConfigIDs as $statisticID ) {
			$allStatisticConfigurations [$statisticID] = $this->getStatisticName ( $statisticID );
		}
		return $allStatisticConfigurations;
	}
	
	
	
	public function loadTempStatisticFromDB() {
		return $this->getStatistic( self::DEFAULT_STATISTIC_ID );
	}
		
	//Liest eine Statistik aus der Datenbank aus und gibt ein Statistik-Objekt zurück
	public function getStatistic($id) {
		global $gDb;
	
		$this->staDBHandler->getTableStatistics()->readDataById($id);
	
		//Metadaten
		$statistic = new Statistic($id, $this->staDBHandler->getTableStatistics()->getValue(TBL_STA_NAME),
				$this->staDBHandler->getTableStatistics()->getValue(TBL_STA_ORG_ID),
				$this->staDBHandler->getTableStatistics()->getValue(TBL_STA_TITLE),
				$this->staDBHandler->getTableStatistics()->getValue(TBL_STA_SUBTITLE),
				$this->staDBHandler->getTableStatistics()->getValue(TBL_STA_STDROLE));
	
		//Tabellen
		$tables = $gDb->query('SELECT * FROM ' . TBL_TABLES .' WHERE ' . TBL_STT_STA_ID . ' = '. $id);
		while($tableRecord = $gDb->fetch_assoc($tables))
		{
			$currentTable = new StatisticTable($tableRecord[TBL_STT_TITLE],
					$tableRecord[TBL_STT_ROLE],
					$tableRecord[TBL_STT_FIRST_COLUMN_LABEL]);
	
			//Zeilen
			$rows = $gDb->query('SELECT * FROM ' . TBL_ROWS .' WHERE ' . TBL_STR_STT_ID . ' = '. $tableRecord[TBL_STT_ID]);
			while($rowRecord = $gDb->fetch_assoc($rows)) {
				$currentTable->addRow(new StatisticTableRow($rowRecord[TBL_STR_LABEL],
						new StatisticCondition(
								$this->switchUnsaveableConditionChars($rowRecord[TBL_STR_FIELD_CONDITION],true),
								$rowRecord[TBL_STR_PROFILE_FIELD])));
			}
	
			//Spalten
			$columns = $gDb->query('SELECT * FROM ' . TBL_COLUMNS .' WHERE ' . TBL_STC_STT_ID . ' = '. $tableRecord[TBL_STT_ID]);
			while($colRecord = $gDb->fetch_assoc($columns)) {
				$currentTable->addColumn(new StatisticTableColumn($colRecord[TBL_STC_LABEL],
						new StatisticCondition(
								$this->switchUnsaveableConditionChars($colRecord[TBL_STC_FIELD_CONDITION],true),
								$colRecord[TBL_STC_PROFILE_FIELD]),
						new StatisticFunction(
								$colRecord[TBL_STC_FUNCTION_MAIN],
								$colRecord[TBL_STC_FUNCTION_ARG]),
						$colRecord[TBL_STC_FUNCTION_TOTAL]));
			}
	
			//Gefüllte Tabelle dem Statistik-Objekt hinzufügen
			$statistic->addTable($currentTable);
		}
		return $statistic;
	}
	
	//Speichert eine neue Statistik in der Datenbank oder aktualisiert eine bestehende.
	//Übergeben wird ein Statistik-Objekt. Hat dieses eine ID, wird die Statistik aktualisiert, sonst neu erstellt.
	public function saveStatistic($statistic) {
	
		$statisticID = $statistic->getDbID();
	
		//Hier wird unterschieden, eine bereits bestehende Statistik aktualisiert oder eine neue gespeichert wird
		if ($statisticID != null) {
			//UPDATE
			$this->staDBHandler->getTableStatistics()->readDataById($statisticID);
			$this->staDBHandler->getTableStatistics()->setValue(TBL_STA_ORG_ID,$statistic->getOrgID());
			$this->staDBHandler->getTableStatistics()->setValue(TBL_STA_TITLE,$statistic->getTitle());
			$this->staDBHandler->getTableStatistics()->setValue(TBL_STA_SUBTITLE,$statistic->getSubtitle());
			$this->staDBHandler->getTableStatistics()->setValue(TBL_STA_STDROLE,$statistic->getStandardRoleID());
			$this->staDBHandler->getTableStatistics()->save();
			//Alte Tabellen vor Update löschen. DB-Constraints führen dazu, dass auch die dazugehörigen Zeilen und Spalten gelöscht werden.
			global $gDb;
			$gDb->query('DELETE FROM ' . TBL_TABLES . ' WHERE ' . TBL_STT_STA_ID . ' = ' . $statisticID);
		} else {
			//NEU SPEICHERN
			$this->staDBHandler->getTableStatistics()->clear();
			$this->staDBHandler->getTableStatistics()->setValue(TBL_STA_ORG_ID,$statistic->getOrgID());
			$this->staDBHandler->getTableStatistics()->setValue(TBL_STA_NAME,$statistic->getName());
			$this->staDBHandler->getTableStatistics()->setValue(TBL_STA_TITLE,$statistic->getTitle());
			$this->staDBHandler->getTableStatistics()->setValue(TBL_STA_SUBTITLE,$statistic->getSubtitle());
			$this->staDBHandler->getTableStatistics()->setValue(TBL_STA_STDROLE,$statistic->getStandardRoleID());
			$this->staDBHandler->getTableStatistics()->save();
			//Statistik-ID des eben gespeicherten Datensatzes lesen
			$statisticID = $this->staDBHandler->getTableStatistics()->getValue(TBL_STA_ID);
		}
	
		//Tabellen speichern
		foreach($statistic->getTables() as $table){
			$this->staDBHandler->getTableTables()->clear();
			$this->staDBHandler->getTableTables()->setValue(TBL_STT_TITLE,$table->getTitle());
			$this->staDBHandler->getTableTables()->setValue(TBL_STT_ROLE,$table->getRoleID());
			$this->staDBHandler->getTableTables()->setValue(TBL_STT_FIRST_COLUMN_LABEL,$table->getFirstColumnLabel());
			$this->staDBHandler->getTableTables()->setValue(TBL_STT_STA_ID,$statisticID);
			$this->staDBHandler->getTableTables()->save();
	
			//ID des eben gespeicherten Datensatzes lesen
			$tableID = $this->staDBHandler->getTableTables()->getValue(TBL_STT_ID);
	
			//Zeilen hinzufügen
			foreach($table->getRows() as $row) {
				$this->staDBHandler->getTableRows()->clear();
				$this->staDBHandler->getTableRows()->setValue(TBL_STR_LABEL,$row->getLabel());
				$this->staDBHandler->getTableRows()->setValue(TBL_STR_FIELD_CONDITION,$this->switchUnsaveableConditionChars($row->getCondition()->getUserCondition(),false));
				$this->staDBHandler->getTableRows()->setValue(TBL_STR_PROFILE_FIELD,$row->getCondition()->getProfileFieldID());
				$this->staDBHandler->getTableRows()->setValue(TBL_STR_STT_ID,$tableID);
				$this->staDBHandler->getTableRows()->save();
			}
	
			//Spalten hinzufügen
			foreach($table->getColumns() as $column) {
				$this->staDBHandler->getTableColumns()->clear();
				$this->staDBHandler->getTableColumns()->setValue(TBL_STC_LABEL,$column->getLabel());
				$this->staDBHandler->getTableColumns()->setValue(TBL_STC_FIELD_CONDITION,$this->switchUnsaveableConditionChars($column->getCondition()->getUserCondition(),false));
				$this->staDBHandler->getTableColumns()->setValue(TBL_STC_PROFILE_FIELD,$column->getCondition()->getProfileFieldID());
				$this->staDBHandler->getTableColumns()->setValue(TBL_STC_FUNCTION_MAIN,$column->getFunction()->getName());
				$this->staDBHandler->getTableColumns()->setValue(TBL_STC_FUNCTION_ARG,$column->getFunction()->getArgument());
				$this->staDBHandler->getTableColumns()->setValue(TBL_STC_FUNCTION_TOTAL,$column->getFunctionTotal());
				$this->staDBHandler->getTableColumns()->setValue(TBL_STC_STT_ID, $tableID);
				$this->staDBHandler->getTableColumns()->save();
			}
		}
	}
	
	private function switchUnsaveableConditionChars($condition, $on){
		if ($on) {
			$search = array("}","{");
			$replace = array(">","<");
		} else {
			$search = array(">","<");
			$replace = array("}","{");
		}
	
		return str_replace($search,$replace,$condition);
	}
	
	//Löscht eine Statistik aus der DB anhand deren ID.
	public function deleteStatistic($id) {
		//Statistik wird gelöscht. DB-Constraints führen dazu, dass auch die dazugehörigen Tabellen gelöscht werden.
		$this->staDBHandler->getTableStatistics()->clear();
		$this->staDBHandler->getTableStatistics()->readDataById($id);
		$this->staDBHandler->getTableStatistics()->delete();
	}
	
	//Gibt die IDs aller in der Datenbank gespeicherten Statistiken für eine bestimmte Organisation zurück
	public function getStatisticIDs($orgId = '1'){
		global $gDb;
		$IDs = array();
	
		//Statistiken der zugehörigen Organisation anzeigen
		$staResultSet = $gDb->query('SELECT * FROM ' . TBL_STATISTICS . '
                                    WHERE ' . TBL_STA_ORG_ID . ' = ' . $orgId);
		while($statisticRecord = $gDb->fetch_assoc($staResultSet))
		{
			//ID 1 ist für die temporäre Speicherung der Statistiken reserviert
			if ($statisticRecord[TBL_STA_ID] != 1) $IDs[] = $statisticRecord[TBL_STA_ID];
		}
	
		return $IDs;
	}
	
	public function loadAllStatisticConfigsArray($currentOrganization){
		$allStatisticConfigIDs = $this->getStatisticIDs($currentOrganization);
		$allStatisticConfigurations = null;
		foreach ($allStatisticConfigIDs as $statisticID){
			$allStatisticConfigurations[$statisticID] = $this->getStatisticName($statisticID);
		}
		return $allStatisticConfigurations;
	}
	
	//Gibt den Namen zu einer Statistik-ID zurück
	public function getStatisticName($id){
		$this->staDBHandler->getTableStatistics()->readDataById($id);
		return $this->staDBHandler->getTableStatistics()->getValue(TBL_STA_NAME);
	}
	
}

?>